Модуль:Спрайт
Модуль для отображения иконок из таблиц спрайтов. -- Внимание: Неосторожные изменения модуля могут привести к проблемам на большом количестве статей! local p = {} -- Создание спрайта function p.base(f) -- Получение параметров local args = f if f mw.getCurrentFrame() then args = require('Модуль:ProcessArgs').merge(true) else f = mw.getCurrentFrame() end -- Настройки по умолчанию local default = { "масштаб" = 1, "формат" = 256, "разм" = 16, "поз" = 1, "выравн" = 'text-top' } -- Получение настроек спрайта local defaultStyle = default if args"настройки" then local settings = mw.loadData('Модуль:' .. args"настройки") if not settings"таблстилей" then -- Создаём отдельную копию текущих настроек по умолчанию: defaultStyle = mw.clone(default) end for k, v in pairs(settings) do defaultk = v end end -- Выбрать настройки указанные или по умолчанию local setting = function(arg) return argsarg or defaultarg end -- Начало сборки кода local sprite = mw.html.create('span'):addClass('sprite') -- создать ... sprite:tag('br') -- добавить -- CSS-стили -- Метод css от mw.html производит очень медленное экранирование входных данных, что тормозит работу в два раза. Вместо -- этого стили будут создаваться вручную, и будут передаваться через метод cssText, который делает только экранирование HTML, -- что куда быстрее. local styles = {} if setting('таблстилей') then -- использовать CSS-классы для указания файла sprite:addClass(setting('имякласса') or mw.ustring.lower(setting('имя'):gsub(' ', '-')) .. '-sprite') else -- указывать файл напрямую table.insert(styles, 'background-image: ') end local class = setting('класс') -- CSS-класс спрайта if class then sprite:addClass(class) end local size = setting('разм') -- размер спрайта в пикселях local v_size = setting('верт_разм') or setting('разм') -- размер спрайта в пикселях в высоту local pos = math.abs(setting('поз')) - 1 -- положение спрайта в таблице local sheetWidth = setting('формат') -- ширина таблицы спрайта в пикселях local tiles = sheetWidth / size -- количество спрайтов в одной строке local left = pos % tiles * size -- горизонтальная координата спрайта local top = math.floor(pos / tiles ) * v_size -- вертикальная координата спрайта local scale = setting('масштаб') -- масштаб спрайта (во сколько раз увеличить или уменьшить размер) local autoscale = setting('автомасштаб') -- автоматическое применение масштабирования local align = setting('выравн') -- выравнивание по вертикали -- Координаты if left > 0 or top > 0 then table.insert(styles, 'background-position: -' .. left * scale .. 'px -' .. top * scale .. 'px') end -- Масштаб if not autoscale and scale ~= defaultStyle"масштаб" then table.insert(styles, 'background-size: ' .. sheetWidth * scale .. 'px auto') end -- Размеры спрайта if size ~= defaultStyle"разм" or (not autoscale and scale ~= defaultStyle"масштаб") then table.insert(styles, 'height: ' .. v_size * scale .. 'px') table.insert(styles, 'width: ' .. size * scale .. 'px') end -- Выравнивание if align ~= defaultStyle"выравн" then table.insert(styles, 'vertical-align: ' .. align) end -- Дополнительный CSS-код, указанный в параметре table.insert(styles, setting('css')) -- Применение полученных CSS-стилей к спрайту. sprite:cssText(table.concat(styles, ';')) -- Собственно спрайт. local root -- Текстовые данные local text = setting('текст') local spriteText if text then root = mw.html.create('span'):addClass('nowrap') spriteText = mw.html.create('span'):addClass('sprite-text'):wikitext(text) end -- Всплывающий текст local title = setting('назв') if title then (root or sprite):attr('title', title) end -- Сборка спрайта if not root then root = mw.html.create() end root:node(sprite) if spriteText then root:node(spriteText) end -- Ссылка local link = setting('ссылка') or "" if link ~= "" and mw.ustring.lower(link) ~= 'none' then -- Внешняя ссылка if link:find('//') then return '.. link .. ' ' .. tostring(root) .. '' end -- Внутренняя ссылка. Поддерживается префикс, что полезно при ссылке на модификации. local linkPrefix = setting('предссылки') or '' return '' .. tostring( root ) .. '' end -- Возвращение полученного кода спрайта return tostring(root) end -- Данная функция предварительно готовит данные для функции p.base, а затем вызывает её. Её следует вызывать на страницах вики-проекта -- (через любой из спрайтовых шаблонов) function p.sprite(f) -- Параметры local args = f if f mw.getCurrentFrame() then args = require('Модуль:ProcessArgs').merge(true) end local categories = {} -- категории local idData = args"данныеID" -- данные по названиям спрайтов и их позициям if not idData then -- Получение настроек local default = {} if args"настройки" then default = mw.loadData( 'Модуль:' .. args"настройки" ) end -- Название таблицы, положение спрайтов local name = args"имя" or default"имя" local ids = mw.loadData( 'Модуль:' .. ( args"IDы" or default"IDы" or name .. 'Спрайт/ID' ) )"IDы" ids = ids"IDы" or ids local id = mw.text.trim( tostring(args1 or '') ) if tonumber(id) then -- числовой идентификатор idData = {"поз" = id} table.insert(categories, 'Категория:Страницы, использующие для спрайтов числовые идентификаторы') else -- именной идентификатор idData = idsid or ids[mw.ustring.lower(id):gsub('_%-%s%++', '-')] end end -- Текущая страница local title = mw.title.getCurrentTitle() -- запретить категории соответственно в подстраницах, на страницах обсуждений и в пространствах участников, -- а также если установлен параметр «некат» local disallowCats = args"некат" or title.isSubpage or title.isTalkPage or title:inNamespace(2) if idData then if type(idData) 'table' then -- новый формат полей ID if idData"устарел" and not disallowCats then table.insert(categories, 'Категория:Страницы с устаревшими названиями спрайтов') end args"поз" = idData"поз" else -- старый формат args"поз" = idData end elseif not disallowCats then table.insert(categories, 'Категория:Страницы с отсутствующими спрайтами') end -- Передача полученных данных функции p.base, её вызов и простановка категорий. return p.base(args), table.concat(categories, '') end -- Ссылки function p.link(f) -- Параметры local args = f if f mw.getCurrentFrame() then args = require('Модуль:ProcessArgs').merge(true) end -- Идентификатор if not args"ID" then args"ID" = args"ид" -- для совместимости со старыми шаблонами end -- Адрес ссылки local link = args1 if args1 and not args"ID" then link = args1:match( '^(.-)%+' ) or args1 end -- Текст ссылки local text = args"текст" or args2 or link -- Указание аргументов для функции p.sprite args1 = args"ID" or args1 args"ссылка" = args"ссылка" or link args"текст" = text -- Вызов p.sprite return p.sprite(args) end -- Документация по таблице спрайтов. Показывает названия спрайтов в таблице и их категории. function p.doc(f) -- Параметры local args = f if f mw.getCurrentFrame() then args = f.args else f = mw.getCurrentFrame() end -- Страницы с параметрами и названиями спрайтов local settingsPage = mw.text.trim(args1) local settings = mw.loadData('Модуль:' .. settingsPage) local idsPage = 'Модуль:' .. (settings"IDы" or settings"имя" .. 'Спрайт/ID') -- Аргументы local spriteargs = {} for k, v in pairs(args) do if type(k) ~= 'number' then spriteargsk = v end end -- Получение данных об уровнях защиты страницы local getProtection = function(title, action, extra) local protections = {'edit'} if extra then table.insert(protections, extra) end local addProtection = function(protection) if protection 'autoconfirmed' then protection = 'editsemiprotected' elseif protection 'sysop' then protection = 'editprotected' end table.insert(protections, protection) end -- прямая защита local direct = title.protectionLevelsaction for _, protection in ipairs(direct) do addProtection(protection) end -- каскадная защита local cascading = title.cascadingProtection.restrictionsaction or {} if #cascading > 0 then table.insert(protections, 'protect') end for _, protection in ipairs(cascading) do addProtection(protection) end return table.concat(protections, ',') end -- Построение документации local body if args.refresh then body = mw.html.create() else -- Данные по спрайту local idsTitle = mw.title.new(idsPage) local spritesheet = settings"изобр" or settings"имя" .. 'CSS.png' local spriteTitle = mw.title.new('Файл:' .. spritesheet) local idsProtection = getProtection(idsTitle, 'edit') local spriteProtection = getProtection(spriteTitle, 'upload', 'upload,reupload') -- Сборка body = mw.html.create('div'):attr({ id = 'spritedoc', 'data-idspage' = idsTitle.id, 'data-idsprotection' = idsProtection, 'data-idstimestamp' = f:callParserFunction('REVISIONTIMESTAMP', idsPage), 'data-spritesheet' = spritesheet, 'data-spriteprotection' = spriteProtection, 'data-pos' = settings"поз" or 1, 'data-refreshtext' = mw.text.nowiki(' ') }) end -- Получение данных по названиям local data = mw.loadData(idsPage) -- Разделы local sections = {} for _, sectionData in ipairs(data"разделы" or {"Некатегоризованные"}) do local sectionTag = body:tag('div'):addClass('spritedoc-section' ):attr( 'data-section-id', sectionData"ID") -- https://phabricator.wikimedia.org/T73594 sectionTag:wikitext(' ', sectionData1, ' ') sections[sectionData"ID"] = {boxes = sectionTag:tag('ul'):addClass('spritedoc-boxes')} end -- Названия спрайтов local keyedData = {} for name, idData in pairs(data"IDы") do table.insert( keyedData, { "ключ" = mw.ustring.lower(name), "имя" = name, "данные" = idData } ) end -- сортировка table.sort(keyedData, function(a, b) return a"ключ" < b"ключ" end) -- Заполнение документации for _, data in ipairs(keyedData) do -- данные local idData = data"данные" local pos = idData"поз" local section = sections[idData"раздел"] local names = sectionpos -- создание спрайта (если у него несколько названий, они группируются) if not names then local box = section.boxes:tag('li'):addClass('spritedoc-box'):attr('data-pos', pos) local lspriteargs = mw.clone(spriteargs) lspriteargs"поз" = pos lspriteargs"настройки" = settingsPage box:tag('div'):addClass('spritedoc-image') :wikitext(p.base(lspriteargs)) names = box:tag('ul'):addClass('spritedoc-names') sectionpos = names end -- название спрайта local nameElem = mw.html.create('li'):addClass('spritedoc-name') local codeElem = nameElem:tag('code'):wikitext( data"имя") -- устарел ли спрайт? if idData"устарел" then codeElem:addClass('spritedoc-deprecated') end names:wikitext(tostring(nameElem)) end if args"обновить" then return '', tostring(body) end return f:callParserFunction('#widget:Stylesheet', {page = 'SpriteDoc'}), tostring(body) end return p